package com.eminem.dao.base;

import com.eminem.annotation.MyField;
import com.eminem.annotation.MyTable;
import com.eminem.model.User;
import com.eminem.model.UserInfo;
import com.eminem.utils.JDBCUtil;
import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.GenerousBeanProcessor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.*;

public class BaseDao<T> {
    private final Class<T> aClass;
    private final String tb_name;
    private final String keyName;

    public BaseDao(Class<T> aClass){
        this.aClass = aClass;
        MyTable table = aClass.getDeclaredAnnotation(MyTable.class);
        if (null != table){
            tb_name = table.value();
            keyName = table.key();
        }else {
            tb_name = null;
            keyName = "id";
        }
    }

    public List<T> findAll(String key, String value) {
        List<T> userList = new ArrayList<>();
        String sql = "select * from "+tb_name+" where "+key+" = ?";
        try {
            QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
            userList = qr.query(sql,new BeanListHandler<>(aClass,new BasicRowProcessor(new GenerousBeanProcessor())),value);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return userList;
    }

    public List<T> findByCols(String cond, Map<String,Object> map){
        List<T> userList = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        sb.append("select * from ").append(tb_name).append(" where ");
        if (null == map || map.isEmpty()){
            sb.delete(sb.lastIndexOf("where"),sb.length());
        }else {
            Set<String> keySet = map.keySet();
            for (String key : keySet) {
                sb.append(key).append("='").append(map.get(key)).append("' ").append(cond).append(" ");
            }
            sb.delete(sb.lastIndexOf(cond),sb.length());
        }
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        try {
            userList = qr.query(sb.toString(),new BeanListHandler<>(aClass));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return userList;
    }

    public int save(Object obj){
        int row = 0;
        StringBuilder sb = new StringBuilder();
        sb.append("insert into ").append(tb_name).append(" values(");
        Class<?> aClass = obj.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if (i==fields.length-1){
                //最后只添加一个问号，其余添加?,
                sb.append("?)");
            }else {
                sb.append("?,");
            }
        }
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        try {
            Object[] params = new Object[fields.length];
            for (int i = 0; i < fields.length; i++) {
                //拿到字段名
                String name = fields[i].getName();
                //第一个字母大写
                String methodName = "get"+name.substring(0,1).toUpperCase()+name.substring(1);
                Method method = aClass.getDeclaredMethod(methodName);
                Object value = method.invoke(obj);
                params[i] = value;
            }
            row = qr.update(sb.toString(),params);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return row;
    }
    public int update(Object obj){
        int row = 0;
        StringBuilder sb = new StringBuilder();
        sb.append("update ").append(tb_name).append(" set ");
        Class<?> aClass = obj.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            MyField myField = field.getAnnotation(MyField.class);
            if (null != myField){
                name = myField.value();
            }
            sb.append(name).append("=?,");
        }
        sb.delete(sb.lastIndexOf(","),sb.length());
        sb.append(" where ").append(keyName).append(" = ?");
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        try {
            Object[] parms = new Object[fields.length + 1];
            Object id = null;
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                String colName = field.getName();
                String name = fields[i].getName();
                MyField myField = field.getAnnotation(MyField.class);
                if (null != myField){
                    colName = myField.value();
                }
                String methodName = "get"+name.substring(0,1).toUpperCase()+name.substring(1);
                Method method = aClass.getDeclaredMethod(methodName);
                Object value = method.invoke(obj);
                if (colName.equals(keyName)){
                    id = value;
                }
                parms[i] = value;
            }
                parms[fields.length] = id;
//            System.out.println(sb.toString());
//            System.out.println(Arrays.toString(parms));
            row = qr.update(sb.toString(),parms);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return row;
    }

    public List<T> findById(Object id){
        List<T> userInfos = new ArrayList<>();
        String sql = "select * from "+tb_name+" where "+keyName+" = ?";
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        try {
            userInfos = qr.query(sql, new BeanListHandler<>(aClass,new BasicRowProcessor(new GenerousBeanProcessor())), id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
//        System.out.println(userInfos.get(0));
        return userInfos;
    }

    public int deleteById(Object id){
        int row = 0;
        String sql = "delete from " + tb_name +" where " + keyName + " = ?";
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        try {
            row = qr.update(sql,id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return row;
    }

}
